package cn.four.hqServer.modules.transfer.service.impl;

import cn.four.hqServer.common.entity.HqCardInfo;
import cn.four.hqServer.common.entity.HqTranUser;
import cn.four.hqServer.common.entity.HqUserInfo;
import cn.four.hqServer.common.enums.CardStatusEnum;
import cn.four.hqServer.common.enums.TranStatusEnum;
import cn.four.hqServer.modules.transfer.dto.TranDto;
import cn.four.hqServer.modules.transfer.dto.TranFlowDto;
import cn.four.hqServer.modules.transfer.mapper.ZnbHqTranUserMapper;
import cn.four.hqServer.modules.transfer.service.ZnbIHqCardInfoService;
import cn.four.hqServer.modules.transfer.service.ZnbIHqTranUserService;
import cn.four.hqServer.modules.transfer.service.ZnbIHqUserInfoService;
import cn.four.hqServer.modules.transfer.vo.TranflowVo;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author znb
 * @since 2023-02-23
 */
@Service
public class HqTranUserServiceImpl extends ServiceImpl<ZnbHqTranUserMapper, HqTranUser>
		implements ZnbIHqTranUserService {

	@Autowired
	private ZnbIHqCardInfoService cardInfoService;

	@Autowired
	private ZnbIHqUserInfoService userInfoService;

	@Autowired
	private ZnbHqTranUserMapper tranUserMapper;

	// @Autowired
	// private BaseMapper<HqTranUser> baseMapper;

	/**
	 * 转账
	 *
	 * 		   PROPAGATION_REQUIRED--支持当前事务，如果当前没有事务，就新建一个事务,最常见的选择。
	 *
	 *         PROPAGATION_SUPPORTS--支持当前事务，如果当前没有事务，就以非事务方式执行。
	 *
	 *         PROPAGATION_MANDATORY--支持当前事务，如果当前没有事务，就抛出异常。
	 *
	 *         PROPAGATION_REQUIRES_NEW--新建事务，如果当前存在事务，把当前事务挂起, 两个事务之间没有关系，一个异常，一个提交，不会同时回滚
	 *
	 *         PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作，如果当前存在事务，就把当前事务挂起。
	 *
	 *         PROPAGATION_NEVER--以非事务方式执行，如果当前存在事务，则抛出异常
	 *
	 *
	 *         isolation = Isolation.REPEATABLE_READ   可重复读

	 * @param tranDto
	 * @return
	 */
	@Override
	// 只能捕捉到 RuntimeException
	@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
	public String account(TranDto tranDto) {
		// 验证付款人银行卡状态
		// 付款人
		HqCardInfo fkr = cardInfoService.getById(tranDto.getCardId());
		Integer state = fkr.getState();
		if (!state.equals(CardStatusEnum.normal.getCode())) {
			return "false";
		}

		// 验证收款人信息(姓名账号状态)
		HqCardInfo skr = cardInfoService.getById(tranDto.getTranCardId());
		// 收款人状态
		Integer state1 = skr.getState();
		// 收款人身份证
		String userId = skr.getUserId();
		// 收款人姓名
		HqUserInfo skrInfo = userInfoService.getById(userId);
		String username = skrInfo.getUsername();
		// 验证收款人的状态和姓名
		if (!state1.equals(CardStatusEnum.normal.getCode()) || !tranDto.getTranName().equals(username)) {
			return "false";
		}
		// 验证付款人密码
		HqUserInfo fkrInfo = userInfoService.getById(fkr.getUserId());
		tranDto.setPassword(DigestUtils.md5Hex(
				tranDto.getPassword() + fkrInfo.getSalt()
		));
		if (!tranDto.getPassword().equals(fkr.getPassword())) {
			return "false";
		}
		// 验证余额是否充足
		BigDecimal tranAmount = tranDto.getTranAmount();
		if (fkr.getBalance().compareTo(tranAmount) == -1) {
			return "false";
		}

		// 我扣钱
		fkr.setBalance(fkr.getBalance().subtract(tranAmount));
		cardInfoService.updateById(fkr);
		// 对方加钱
		skr.setBalance(skr.getBalance().add(tranAmount));
		cardInfoService.updateById(skr);
		// 记录交易流水表
		HqTranUser fkrTran = new HqTranUser();
		fkrTran.setCardId(tranDto.getCardId());
		fkrTran.setBusinessType(0);
		fkrTran.setTranAmount(tranAmount);
		fkrTran.setTranAfterAmount(fkr.getBalance());
		fkrTran.setTranTime(LocalDateTime.now());
		fkrTran.setTranName(tranDto.getTranName());
		fkrTran.setTranCardId(tranDto.getTranCardId());
		fkrTran.setNotes(tranDto.getNotes());
		baseMapper.insert(fkrTran);

		HqTranUser skrTran = new HqTranUser();
		skrTran.setCardId(skr.getCardId());
		skrTran.setBusinessType(1);
		skrTran.setTranAmount(tranAmount);
		skrTran.setTranAfterAmount(skr.getBalance());
		skrTran.setTranTime(LocalDateTime.now());
		skrTran.setTranName(userInfoService.getById(fkr.getUserId()).getUsername());
		skrTran.setTranCardId(fkr.getCardId());
		skrTran.setNotes(tranDto.getNotes());
		baseMapper.insert(skrTran);

		return "true";
	}

	@Override
	public Page<TranflowVo> tranflow(TranFlowDto tranFlowDto) {
		Page<HqTranUser> page = new Page<>();
		LambdaQueryWrapper<HqTranUser> wrapper = new LambdaQueryWrapper<HqTranUser>();
		wrapper.eq(HqTranUser::getCardId,tranFlowDto.getCardId())
				.ge(HqTranUser::getTranTime,tranFlowDto.getStartTime())
				.lt(HqTranUser::getTranTime,tranFlowDto.getEndTime());
		if(tranFlowDto.getType() != null){
			wrapper.eq(HqTranUser::getBusinessType,tranFlowDto.getType());
		}
		this.page(page,wrapper);

		Page<TranflowVo> res = new Page<>();
		BeanUtils.copyProperties(page, res);
		List<HqTranUser> records = page.getRecords();
		List<TranflowVo> vos = new ArrayList<>();
		for (HqTranUser record : records) {
			TranflowVo tranflowVo = new TranflowVo();
			BeanUtils.copyProperties(record,tranflowVo);
			Integer businessType = record.getBusinessType();
			switch (businessType){
				case 0:tranflowVo.setBusinessType("转账支出");break;
				case 1:tranflowVo.setBusinessType("转账收入");break;
				case 2:tranflowVo.setBusinessType("存款");break;
				case 3:tranflowVo.setBusinessType("取款");break;
				case 4:tranflowVo.setBusinessType("结息");break;
			}
			vos.add(tranflowVo);
		}
		res.setRecords(vos);
		return res;
	}


}
